#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "key_driver.h"
#include "configuration.h"
#include "clock_function.h"

static const char *TAG = "key driver";
QueueHandle_t keyEvenqueue = NULL;//按键中断消息队列句柄

//创建中断函数 必须放在IRAM_ATTR里
static void IRAM_ATTR key_intrhandle(void *arg)
{
    uint32_t key_num = (uint32_t)arg;

    gpio_set_intr_type(key_num,GPIO_INTR_DISABLE);//禁用已触发的gpio中断防止按键抖动频繁触发
    xQueueSendFromISR(keyEvenqueue,&key_num,NULL);//把中断信息发送出去
}
//接收按键中断信息任务
static void key_intr_recv_task()
{
    uint32_t keyrEev;

    while(1)
    {
        if(xQueueReceive(keyEvenqueue,&keyrEev,portMAX_DELAY))
        {
            if(gpio_get_level(keyrEev) == 0)
            {
                //要做的任务
                if(keyrEev == key1) xEventGroupSetBits(KeyEventHandle,key1_event);
                if(keyrEev == key2) xEventGroupSetBits(KeyEventHandle,key2_event);
                if(keyrEev == key3) xEventGroupSetBits(KeyEventHandle,key3_event);
            }
            gpio_set_intr_type(keyrEev,GPIO_INTR_LOW_LEVEL);//恢复gpio中断
        }
        vTaskDelay(300 / portTICK_PERIOD_MS);
    }

}

void key_init()
{
    gpio_config_t keyCfg;

    //配置gpio
    keyCfg.intr_type = GPIO_INTR_LOW_LEVEL;//低电平触发
    keyCfg.mode = GPIO_MODE_INPUT;
    keyCfg.pin_bit_mask = (1ULL<<key1 | 1ULL<<key2 | 1ULL<<key3);
    keyCfg.pull_down_en = 0;
    keyCfg.pull_up_en = 1;//上拉
    gpio_config(&keyCfg);

    gpio_install_isr_service(0);//注册gpio中断服务
    gpio_isr_handler_add(key1,key_intrhandle,(void*)key1);//把gpio中断关联到中断服务函数
    gpio_isr_handler_add(key2,key_intrhandle,(void*)key2);//把gpio中断关联到中断服务函数
    gpio_isr_handler_add(key3,key_intrhandle,(void*)key3);//把gpio中断关联到中断服务函数
    //gpio_isr_handler_remove(key4);//移除引脚gpio中断

    //创建消息队列以及消息接收任务
    keyEvenqueue = xQueueCreate(10,sizeof(uint32_t));
    if(keyEvenqueue == NULL) ESP_LOGE(TAG,"create queue fail!");
    else xTaskCreate(key_intr_recv_task,"key_intr_recv_task",1024,NULL,20,NULL);

    ESP_LOGI(TAG,"config key done.");
}